package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import lombok.val;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.geom.QuadCurve2D;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Transactional  //回滚
    @Override
    public void deductBalance(Long id, Integer money) {
        //1.查询用户
        User user = this.getById(id);
        //2.校验用户状态
        if (user == null || user.getStatus() == UserStatus.FROZEN){
            throw new RuntimeException("用户状态异常!");
        }
        //3.检验余额是否充足
        if (user.getBalance() < money){
            throw new RuntimeException("用户余额不足!");
        }
        //4.扣除余额 update user set bablance = balance -?
        baseMapper.deductBalance(id,money);
        //扣除余额，如果扣除余额到0了，就把用户状态改为2
        int remainBalance = user.getBalance() - money;
        lambdaUpdate()
                .set(User::getBalance, remainBalance)
                .set(remainBalance == 0,User::getStatus, 2)
                .eq(User::getId, id)
                .eq(User::getBalance,user.getBalance()) //乐观锁,保证只有1个线程.
                .update();       //必须跟上update  否则不会执行
    }
    @Override
    public List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {
    return lambdaQuery()//不需要在new wrapper
               .like(name !=null,User::getUsername, name)
               .eq(status != null,User::getStatus, status)
               .ge(minBalance != null,User::getBalance, minBalance)
               .le(maxBalance != null,User::getBalance, maxBalance)
               .list();
    }

    @Override
    public UserVO queryUserAndAddressById(Long id) {
        //1.查询用户
        User user = this.getById(id);
        if (user == null){
            throw new RuntimeException("用户为空");
        }
        //2.查询收获地址
        List<Address> list = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, user.getId())
                .list();
        //3.处理vo
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        userVO.setAddress(BeanUtil.copyToList(list, AddressVO.class));
        return userVO;
    }

    @Override
    public List<UserVO> queryListUserAndAddressById(List<Long> ids) {
        //1.批量查询用户
        List<User> users = this.listByIds(ids);
        if (CollUtil.isEmpty(users)){
            return Collections.emptyList();
        }
        //2.批量查地址
        //拿到上面的ids
        //我是拿到每个用户，然后去查，我这样性能太低了.
       /* for (User user : users) {
            List<Address> addresslist = Db.lambdaQuery(Address.class)
                    .eq(Address::getUserId, user.getId())
                    .list();
            //3.处理vo
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            userVO.setAddress(BeanUtil.copyToList(addresslist, AddressVO.class));
            usersList.add(userVO);
        }
      return usersList;*/
        //2.1获取用户id集合
        List<Long> idsList = users.stream()
                .map(user -> user.getId())
                .collect(Collectors.toList());
        //2.2获取地址
        List<Address> addressList = Db.lambdaQuery(Address.class)  //是所有用户的地址
                .in(Address::getUserId, idsList)
                .list();
        //2.3将地址分类，用户地址集合分组处理，相同用户放在一个集合
        Map<Long, List<Address>> addresslistMap = new HashMap<>(0);
        if (CollUtil.isNotEmpty(addressList)){
                      addresslistMap = addressList.stream()
                    .collect(Collectors.groupingBy(Address::getUserId)); //key 为用户id
        }
        //3.转换vo
        //3.1 创建Vo 集合
        List<UserVO> userVOList = new ArrayList<>(users.size());
        //3.2遍历
        for (User user : users) {
            //转换User的Po 到 Vo
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            userVOList.add(vo);
            //转换地址vo
            vo.setAddress(BeanUtil.copyToList(addresslistMap.get(user.getId()), AddressVO.class));
        }
        return userVOList;
    }

    @Override
    public List<AddressVO>  queryUserAddressById(Long id) {
        //拿到用户，判断用户的状态
        User user = this.getById(id);
        if (user == null){
            throw new RuntimeException("用户为空");
        }
        if(user.getStatus() == UserStatus.FROZEN){
            throw new RuntimeException("用户被冻结");
        }
        List<Address> addressList = Db.lambdaQuery(Address.class)
                .eq(Address::getUserId, user.getId())
                .list();
        //转换地址
        return BeanUtil.copyToList(addressList,AddressVO.class);
    }

    @Override
    public PageDTO<UserVO> queryPageUsers(UserQuery userQuery) {
        ////把分页相关的进行封装   PageQuery 转为MP 的Page对象
        //1.分页条件
        String name = userQuery.getName();
        Integer status = userQuery.getStatus();
        /*Page<User> page = Page.of(userQuery.getPageNo(), userQuery.getPageSize());
        //1.1排序条件
        if(StringUtils.isNotEmpty(userQuery.getSortBy())){
            //不为空
            page.addOrder(new OrderItem(userQuery.getSortBy(),true));
        }else
        {
            //为空
            page.addOrder(new OrderItem("update_time",false));
        }*/
        //使用封装的
        Page<User>page = userQuery.toMpPageDefaultSortByUpdate();

        //2.分页查询
        Page<User> p  = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);
        //3.封装vo结果
       /* PageDTO<UserVO> dto = new PageDTO<>();
        dto.setTotal(p.getTotal()); //总条数
        dto.setPages(p.getPages()); //总页数
        List<User> records = p.getRecords();
        if (CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
        }
        dto.setList(BeanUtil.copyToList(records, UserVO.class));//转成Vo集合
        //4.分页结果
        return dto;*/
       // return PageDTO.of(p,user -> BeanUtil.copyProperties(user,UserVO.class));
        return PageDTO.of(p,user -> {//自定义转换器
            //1.拷贝基础属性
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            //2.处理特殊逻辑
            //举个例子
            vo.setUsername(vo.getUsername().substring(0,vo.getUsername().length()-2)+"**");
            return vo;
        });
    }
}
